#include "Col.ph"
#ifdef __GNUG__
#pragma implementation
#endif

#include "RobustHashTable.h"
#include "Class.h"

#include "Set.h"

//---- RobustHashTable ---------------------------------------------------------

NewMetaImpl(RobustHashTable,HashTable, (TVP(tab,capacity)));

RobustHashTable::RobustHashTable(Set *aClient,int initCapacity, pEqualFunc eq,
		pHashFunc hsh, int *sz) : HashTable(initCapacity, eq, hsh, sz)
{
	client= aClient;
	Init();
}

RobustHashTable::~RobustHashTable()
{
	SafeDelete(tab);
	SafeDelete(seq);
}

void RobustHashTable::Init()
{
	int i;
	TabEntry entry;
		
	tab= new Object *[capacity + 1];
	seq= new TabEntry[capacity + 1];

	entry.nxt= capacity;
	entry.prv= capacity;
	for ( i= 0; i <= capacity; i++ ) {
		tab[i]= 0;
		seq[i]= entry;
	}
}

void RobustHashTable::Empty(int newCapacity)
{
	SafeDelete(tab);
	SafeDelete(seq);

	CalcBounds(newCapacity);
	*size= 0;
	Init();
	Changed();
}

//----- iterator support --------

void *RobustHashTable::AtNextIndex(int &i)
{
	i= seq[i].nxt;
	return tab[i];
}

void *RobustHashTable::AtPrevIndex(int &i)
{
	i= seq[i].prv;
	return tab[i];
}

int RobustHashTable::GetInitialIndex()
{
	return capacity;
}

//---- table primitives --------

void *RobustHashTable::KeyAt(int i)
{
	return tab[i];
}

void RobustHashTable::SetKeyAt(void *obj, int i)
{
	TabEntry *prvp, *nxtp;

	tab[i]= (Object *) obj;

	nxtp= &seq[capacity];
	prvp= &seq[nxtp->prv];
	seq[i].Set(nxtp->prv, prvp->nxt);
	prvp->nxt= i;
	nxtp->prv= i;
}

void RobustHashTable::NullAt(int i)
{
	int prv, nxt;

	tab[i]= 0;

	prv= seq[i].prv;
	nxt= seq[i].nxt;
	seq[prv].nxt= nxt;
	seq[nxt].prv= prv;
	seq[i].prv= capacity;
	seq[i].nxt= capacity;
}

void RobustHashTable::Swap(int i, int j)
{
	Object *tmp;
	int prv, nxt;
	TabEntry entry;

	tmp= tab[i];
	tab[i]= tab[j];
	tab[j]= tmp;

	entry= seq[i];
	seq[i]= seq[j];
	seq[j]= entry;
	prv= seq[i].prv;
	nxt= seq[i].nxt;
	seq[prv].nxt= i;
	seq[nxt].prv= i;
}

void RobustHashTable::RemoveSlot(int slot)
{
	if ( client->HasIterators() ) {
		client->SaveItersPosition(slot);
		HashTable::RemoveSlot(slot);
		client->ResetItersPosition();
	} else
		HashTable::RemoveSlot(slot);
}

void RobustHashTable::Rehash(int newCapacity)
{
	if ( newCapacity > capacity && client->HasIterators() ) {
		client->SaveItersPosition(cInvalidIndex);
		HashTable::Rehash(newCapacity);
		client->ResetItersPosition();
	} else
		HashTable::Rehash(newCapacity);
		// rehash due to removal - iterator's position already saved
}

HashTable *RobustHashTable::MakeNew(int initCapacity)
{
	return new RobustHashTable(client, initCapacity, equal, hash);
}

void RobustHashTable::Assign(HashTable *ht)
{
	RobustHashTable *rht= (RobustHashTable *) ht;

	HashTable::Assign(ht);
	SafeDelete(tab);
	SafeDelete(seq);
	tab= rht->tab;
	seq= rht->seq;
	rht->tab= 0;
	rht->seq= 0;
}


